package com.example.rxtxdemo.rxtx;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson2.JSONObject;
import com.example.rxtxdemo.rxtx.demo.SerialPortManager;
import com.fazecast.jSerialComm.SerialPort;
import com.google.common.collect.Maps;
import gnu.io.PortInUseException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("test")
@RequiredArgsConstructor
public class RxtxRest1 {


    @GetMapping("sendData")
    public Map<String, Object> sendData(@RequestParam String portName, @RequestParam Integer baudRate, @RequestParam String content) {
        Map<String, Object> map = Maps.newHashMap();
        byte[] sendBytes = HexUtil.decodeHex(content);

        byte[] bytes1 = SerialPortManager.sendAndRead(portName, baudRate, sendBytes, 3000);
        String receiveMsg = HexUtil.encodeHexStr(bytes1, false);
        map.put("msg", receiveMsg);
        return map;
    }


    /**
     * @throws PortInUseException 串口已经被占用
     */
    public static void main(String[] args) throws PortInUseException {
        //打开串口，返回一个串口对象 参数：串口号 波特率
        SerialPort serialPort = SerialPortManager.openPort("COM1", 10000);
        //给当前串口对象设置监听器
        SerialPortManager.addListener(serialPort, () -> {

            //当前监听器监听到的串口返回数据 back
            byte[] back = SerialPortManager.readFromPort(serialPort);
        });
        //当前向串口发送的数据（模拟假数据）
        byte[] content = new byte[10];
        //向当前串口发送数据
        SerialPortManager.sendToPort(serialPort, content);
    }



    @GetMapping("sendDataListener")
    public Map<String, Object> sendDataListener(@RequestParam String portName, @RequestParam Integer baudRate, @RequestParam String content) {
        Map<String, Object> map = Maps.newHashMap();
        SerialPort serialPort = SerialPortManager.openPort(portName, baudRate);
        SerialPortManager.addListener(serialPort, () -> {
            ThreadUtil.sleep(3000);
            //当前监听器监听到的串口返回数据 back
            byte[] receiveBytes = SerialPortManager.readFromPort(serialPort);
            String receiveMsg = HexUtil.encodeHexStr(receiveBytes, false);
            map.put("msg", receiveMsg);
            log.info(String.format("分站%s 接收串口指令：%s", 70, receiveMsg));
        });
        //当前向串口发送的数据（模拟假数据）
        //向当前串口发送数据
        SerialPortManager.sendToPort(serialPort, HexUtil.decodeHex(content));
//        SerialPortManager.closePort(serialPort);
        return map;
    }

    @GetMapping("test21")
    public String test21() {
        String s = SerialTools.toHex(70);
        if (s.length() == 1) s = "0" + s;
        String check = SerialTools.makeCheckSum("CAFC" + s + "4A000100");
        String sendMsg = "CAFC" + s + "4A000100" + check + "EE";
        sendMsg = sendMsg.toUpperCase();
        byte[] bytes = SerialTools.hexToByteArray(sendMsg);
        log.info(String.format("分站%s 发送串口指令：%s", 70, sendMsg));
        SerialPort jSerialPort = SerialPortManager.openPort("COM3", 1200);
        byte[] bytes1 = SerialPortManager.sendAndRead(jSerialPort, bytes, 3000);
        return SerialTools.byteToHex(bytes1);
    }


    @GetMapping("ports")
    public Map<String, Object> test() {
        Map<String, Object> map = Maps.newHashMap();
        List<String> ports = SerialPortManager.findPorts();
        ports.forEach(port -> map.put(port, SerialPort.getCommPort(port).isOpen()));
        return map;
    }


    @GetMapping("open")
    public Map<String, Object> open(@RequestParam String portName, @RequestParam Integer baudRate) {
        Map<String, Object> map = Maps.newHashMap();
        SerialPort port = SerialPortManager.openPort(portName, baudRate);
        log.info("串口状态 {} ", port.isOpen());
        map.put("port", JSONObject.toJSONString(port));
        SerialPortManager.closePort(port);
        return map;
    }


    @GetMapping("status")
    public Boolean status(@RequestParam String portName) {
        SerialPort serialPort = SerialPort.getCommPort(portName);
        log.info("串口状态 {} ", serialPort.isOpen());
        return serialPort.isOpen();
    }


    @GetMapping("test1")
    public void test1() {
        SerialPort[] serialPorts = SerialPort.getCommPorts();
        //查找所有串口
        for (SerialPort serialPort : serialPorts) {
            //打印串口名称，如COM4
            System.out.println("Port:" + serialPort.getSystemPortName());
            //打印串口类型，如USB Serial
            System.out.println("PortDesc:" + serialPort.getPortDescription());
            //打印串口的完整类型，如USB-SERIAL CH340(COM4)
            System.out.println("PortDesc:" + serialPort.getDescriptivePortName());
            //获取到第一个串口
            //设置波特率为112500
            serialPort.setBaudRate(112500);
            //设置超时
            serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 1000, 1000);
            serialPort.setRTS();//设置RTS。也可以设置DTR
            //设置串口的控制流，可以设置为disabled，或者CTS, RTS/CTS, DSR, DTR/DSR, Xon, Xoff, Xon/Xoff等
            serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
            //一次性设置所有的串口参数，第一个参数为波特率，默认9600；第二个参数为每一位的大小，默认8，可以输入5到8之间的值；第三个参数为停止位大小，只接受内置常量，可以选择(ONE_STOP_BIT, ONE_POINT_FIVE_STOP_BITS, TWO_STOP_BITS)；第四位为校验位，同样只接受内置常量，可以选择 NO_PARITY, EVEN_PARITY, ODD_PARITY, MARK_PARITY,SPACE_PARITY。
            serialPort.setComPortParameters(112500, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
            if (!serialPort.isOpen()) {
                //判断串口是否打开，如果没打开，就打开串口。打开串口的函数会返回一个boolean值，用于表明串口是否成功打开了
                boolean openFlag = serialPort.openPort();
                log.info("打开串口  == {}", openFlag);
            }
            //关闭串口。该函数同样会返回一个boolean值，表明串口是否成功关闭
            boolean closeFlag = serialPort.closePort();
            log.info("关闭== {}", closeFlag);
        }
    }


    @GetMapping("close")
    public Map<String, Object> close(@RequestParam String portName) {
        Map<String, Object> map = Maps.newHashMap();
        SerialPort serialPort = SerialPort.getCommPort(portName);
        SerialPortManager.closePort(serialPort);
        log.info("串口已关闭");
        map.put(portName, serialPort.closePort());
        return map;
    }




}
